package ga;

import ga.ObjTipo.TipoObjTipo;

//TODO quitar el Undef una vez debuggueado
abstract public class Instruccion {
	public enum ICOD {
		SUM, RESTA, MUL, DIV, AND, OR, EQ, NEQ, GT, GE, LT, LE, IR_F, IR_A, APILA, 
		DESAPILA_DIR, APILA_DIR, APILA_TRUE, APILA_FALSE, NOT, MENOS, IR_IND, DESAPILA,
		APILA_IND, DESAPILA_IND, COPIA, LEER, ESCRIBIR ,LIBERAR, RESERVAR, INDEFINIDO, MOVER};
	
//	abstract public void ejecuta(TinyVM vm);
   
	abstract public ICOD ci();
    
    public int arg1()  
    {
    	throw new UnsupportedOperationException("arg1");   
    } 
    
    public TipoObjTipo arg2()  
    {
    	throw new UnsupportedOperationException("arg2");   
    } 
    
    public static class ISuma extends Instruccion {
       ISuma() {
    	   
       } 
       
       public ICOD ci () {
    	   return ICOD.SUM;
       }
       
       public String toString() {
    	   return "SUMA";
       }
    }
    
    public static class IResta extends Instruccion {
        IResta() {
        	
        } 
        
        public ICOD ci () {
        	return ICOD.RESTA;
        }
        
        public String toString() {
        	return "RESTA";
        }
     }
    
    public static class IMul extends Instruccion{
       IMul() {
    	   
       } 
       
       public ICOD ci () {
    	   return ICOD.MUL;
       }
       
       public String toString() {
    	   return "MUL";
       }  
    }
    
    public static class IDiv extends Instruccion {
        IDiv() {
        	
        } 
        
        public ICOD ci () {
        	return ICOD.DIV;
        }
        
        public String toString() {
        	return "DIV";
        }
     }
    
    public static class IOr extends Instruccion {
        IOr() {
        	
        } 
        
        public ICOD ci () {
        	return ICOD.OR;
        	}
        
        public String toString() {
        	return "OR";
        }
     }
    
    public static class IAnd extends Instruccion {
        IAnd() {
        	
        } 
        
        public ICOD ci () {
        	return ICOD.AND;
        }
        
        public String toString() {
        	return "AND";
        }        
     }
    
    public static class IEq extends Instruccion {
        IEq() {
        	
        } 
        
        public ICOD ci () {
        	return ICOD.EQ;
        }
        
        public String toString() {
        	return "EQ";
        }
     }
    
    public static class INeq extends Instruccion {
        INeq() {
        	
        } 
        
        public ICOD ci () {
        	return ICOD.NEQ;
        }
        
        public String toString() {
        	return "NEQ";
        }
     }
    
    public static class IGt extends Instruccion {
        IGt() {
        	
        } 
        
        public ICOD ci () {
        	return ICOD.GT;
        }
        
        public String toString() {
        	return "GT";
        }
     }
    
    public static class IGe extends Instruccion {
        IGe() {
        	
        } 
        
        public ICOD ci () {
        	return ICOD.GE;
        }
        
        public String toString() {
        	return "GE";
        }
     }
    
    public static class ILt extends Instruccion {
        ILt() {
        	
        } 
        
        public ICOD ci () {
        	return ICOD.LT;
        }
        
        public String toString() {
        	return "LT";
        }
     }
    
    public static class ILe extends Instruccion {
        ILe() {
        	
        }
        
        public ICOD ci () {
        	return ICOD.LE;
        }
        
        public String toString() {
        	return "LE";
        }
     }
    
    public static class Ir_f extends Instruccion {
        Ir_f(Integer val) {
              this.val = val;    
         }
        
        Ir_f(int val) {
            this.val = val;    
        }
        
         public ICOD ci () {
        	 return ICOD.IR_F;
         }
         
         public int arg1() {
        	 return val;
         }
         
         public String toString() {
        	 return "IR_F("+val+")";
         }
         
         private Integer val;
     }
    
    public static class Ir_a extends Instruccion {
        Ir_a(Integer val) {
        	this.val = val;  
         } 
        
        Ir_a(int val) {
              this.val = val;    
         }
        
         public ICOD ci () {
        	 return ICOD.IR_A;
         }
         
         public int arg1() {
        	 return val;
         }
         
         public String toString() {
        	 return "IR_A("+val+")";
         }
         
         private Integer val;
     }
    
    public static class IApila extends Instruccion {
       IApila(String val) {
          try {
            this.val = Integer.valueOf(val).intValue();    
          }
          catch(NumberFormatException e) {
            this.val = 0;   
          }
       }   
       
       public ICOD ci () {
    	   return ICOD.APILA;
       }
       
       public int arg1() {
    	   return val;
       }
       
       public String toString() {
    	   return "APILA("+val+")";
       }
       
       private int val;
     }
 
    public static class IApila_dir extends Instruccion {
        IApila_dir(String val) {
           try {
             this.val = Integer.valueOf(val).intValue();    
           }
           catch(NumberFormatException e) {
             this.val = 0;   
           }
        }   
        
        public ICOD ci () {
        	return ICOD.APILA_DIR;
        }
        
        public int arg1() {
        	return val;
        }
        
        public String toString() {
        	return "APILA_DIR("+val+")";
        }
        
        private int val;
      }
    
    public static class IDesapila_dir extends Instruccion {
    	IDesapila_dir(String val) {
           try {
             this.val = Integer.valueOf(val).intValue();    
           }
           catch(NumberFormatException e) {
             this.val = 0;   
           }
        }   
    	
        public ICOD ci () {
        	return ICOD.DESAPILA_DIR;
        }
        
        public int arg1() {
        	return val;
        }
        
        public TipoObjTipo arg2() {
        	return arg2;
        }
        
        public String toString() {
        	return "DESAPILA_DIR("+val+")";
        }
        
        private int val;
        private TipoObjTipo arg2;
    }

    public static class IApila_true extends Instruccion {
        IApila_true() {
        	
        } 
        
        public ICOD ci () {
        	return ICOD.APILA_TRUE;
        }
        
        public String toString() {
        	return "APILA_TRUE";
        }
      }
    
    public static class IApila_false extends Instruccion {
        IApila_false() {
        	
        }   
        
        public ICOD ci () {
        	return ICOD.APILA_FALSE;
        }
        
        public String toString() {
        	return "APILA_FALSE";
        }
      }
    
    public static class INot extends Instruccion {
    	INot() {
    		
    	} 
    	
        public ICOD ci () {
        	return ICOD.NOT;
        }
        
        public String toString() {
        	return "NOT";
        }
     }
    
    public static class IMenos extends Instruccion {
    	IMenos() {
    		
    	} 
    	
        public ICOD ci () {
        	return ICOD.MENOS;
        }
        
        public String toString() {
        	return "MENOS";
        }
     }
    
    public static class Ir_Ind extends Instruccion {
    	 Ir_Ind() {
         } 
    	
         public ICOD ci () {
        	 return ICOD.IR_IND;
         }
         
         public String toString() {
        	 return "IR_IND";
         }        
     }
    
    public static class ICopia extends Instruccion {
    	ICopia() {
    		
    	} 
    	
        public ICOD ci () {
        	return ICOD.COPIA;
        }
        
        public String toString() {
        	return "COPIA";
        }
     }
    
    public static class IApilaInd extends Instruccion {
    	IApilaInd() {
    		
    	} 
    	
        public ICOD ci () {
        	return ICOD.APILA_IND;
        }
        
        public String toString() {
        	return "APILA_IND";
        }
     }
    
    public static class IDesapilaInd extends Instruccion {
    	IDesapilaInd() {
    		
    	} 
    	
        public ICOD ci () {
        	return ICOD.DESAPILA_IND;
        }
        
        public String toString() {
        	return "DESAPILA_IND";
        }
     }
    
    public static class IDesapila extends Instruccion {
    	IDesapila() {
    		
    	} 
    	
        public ICOD ci () {
        	return ICOD.DESAPILA;
        }
        
        public String toString() {
        	return "DESAPILA";
        }
     }
    
    public static class ILeer extends Instruccion {
    	ILeer(TipoObjTipo t) {
    		this.val = t;
    	} 
    	
        public ICOD ci () {
        	return ICOD.LEER;
        }
        
        public String toString() {
        	return "LEER("+val+")";
        }
        
        private TipoObjTipo val;
        
        public TipoObjTipo arg2() {
        	return val;
        }
    }
    
    public static class IEscribir extends Instruccion {
    	 IEscribir(TipoObjTipo t) {
    		 this.val = t;
    	 } 
    	 
         public ICOD ci () {
        	 return ICOD.ESCRIBIR;
         }
         public String toString() {
        	 return "ESCRIBIR("+val+")";
         }
         
         private TipoObjTipo val;
         
         public TipoObjTipo arg2() {
        	 return val;
         }
    }
    
    public static class IReservar extends Instruccion {
    	IReservar (Integer val) {
    		this.val = val;
        }  
    	
        public ICOD ci () {
        	return ICOD.RESERVAR;
        }
        
        public int arg1() {
        	return val;
        }
        
        public String toString() {
        	return "RESERVAR("+val+")";
        }
        
        private int val;
   }
    
    public static class ILiberar extends Instruccion {
    	ILiberar(Integer val) {
            this.val = val;
        }  
    	
        public ICOD ci () {
        	return ICOD.LIBERAR;
        }
        
        public int arg1() {
        	return val;
        }
        
        public String toString() {
        	return "LIBERAR("+val+")";
        }
        
        private int val;
    }
    public static class IIndefinido 			extends Instruccion {
    	String eti;
    	IIndefinido(String et) {eti = et;} 
        public ICOD ci () {return ICOD.INDEFINIDO;}
        public String toString() {return "INDEFINIDO("+eti+")";}
     }

    public static class IMover extends Instruccion {
    	IMover(Integer val) {
            this.val = val;
        }  
    	
        public ICOD ci () {
        	return ICOD.MOVER;
        }
        
        public int arg1() {
        	return val;
        }
        public String toString() {
        	return "MOVER("+val+")";
        }
        private int val;
     }
    
     public static Instruccion nuevaISuma() {
        if (isuma==null) {
           isuma = new ISuma(); 
        } 
        
        return isuma;
     }
     
     public static Instruccion nuevaIResta() {
         if (iresta==null) {
            iresta = new IResta(); 
         } 
         
         return iresta;
      }
     
     public static Instruccion nuevaIMul() {
        if (imul==null) {
           imul = new IMul(); 
        } 
        
        return imul;
     }
     
     public static Instruccion nuevaIDiv() {
         if (idiv==null) {
            idiv = new IDiv(); 
         } 
         
         return idiv;
      }
     
     public static Instruccion nuevaIOr() {
         if (ior==null) {
            ior = new IOr(); 
         } 
         
         return ior;
      }
     
     public static Instruccion nuevaIAnd() {
         if (iand==null) {
            iand = new IAnd(); 
         } 
         
         return iand;
      }
     
     public static Instruccion nuevaIEq() {
         if (ieq==null) {
            ieq = new IEq(); 
         } 
         
         return ieq;
      }
     
     public static Instruccion nuevaINeq() {
         if (ineq==null) {
            ineq = new INeq(); 
         } 
         
         return ineq;
      }
     
     public static Instruccion nuevaIGt() {
         if (igt==null) {
            igt = new IGt(); 
         } 
         
         return igt;
      }
     
     public static Instruccion nuevaIGe() {
         if (ige==null) {
            ige = new IGe(); 
         } 
         
         return ige;
      }
     
     public static Instruccion nuevaILt() {
         if (ilt==null) {
            ilt = new ILt(); 
         } 
         
         return ilt;
      }
     
     public static Instruccion nuevaILe() {
         if (ile==null) {
            ile = new ILe(); 
         } 
         
         return ile;
      }
     
     public static Instruccion nuevaIr_f(Integer val) {
         return new Ir_f(val); 
      }
     
     public static Instruccion nuevaIr_a(Integer val) {
         return new Ir_a(val); 
      } 
     
     public static Instruccion nuevaIApila(String val) {
        return new IApila(val); 
     }
     
     public static Instruccion nuevaIApila_dir(String val){
    	 return new IApila_dir(val); 
     }

     public static Instruccion nuevaIDesapila_dir(String val) {
         return new IDesapila_dir(val); 
      }
 
     public static Instruccion nuevaIApila_true() {
         if (ipatrue==null) {
        	 ipatrue = new IApila_true(); 
         } 
         
         return ipatrue;
      }
     
     public static Instruccion nuevaIApila_false() {
         if (ipafalse==null) {
        	 ipafalse = new IApila_false(); 
         } 
         
         return ipafalse;
      }
     
     public static Instruccion nuevaINot() {
         if (inot==null) {
         	inot = new INot(); 
         } 
         
         return inot;
      }   
     
     public static Instruccion nuevaIMenos() {
         if (imenos==null) {
            imenos = new IMenos(); 
         } 
         
         return imenos;
      }
     
     public static Instruccion nuevaIr_Ind() {
    	 if (iirind==null) {
    		 iirind = new Ir_Ind(); 
          } 
    	 
          return iirind;
      } 

	 public static Instruccion nuevaICopia() {
		if (icopia==null) {
 			icopia = new ICopia(); 
         } 
		
         return icopia;
	 }

	 public static Instruccion nuevaIApilaInd() {
		if (iapilaind==null) {
 			iapilaind = new IApilaInd(); 
         } 
		
         return iapilaind;
	 }
	 
	 public static Instruccion nuevaIDesapilaInd() {
		if (idesapilaind==null) {
 			idesapilaind = new IDesapilaInd(); 
         } 
		
         return idesapilaind;
	 }   
	 
 	 public static Instruccion nuevaIDesapila() {
		if (idesapila==null) {
 			idesapila = new IDesapila(); 
         } 
		
         return idesapila;
	 }
 	 
	 public static Instruccion nuevaILeer(TipoObjTipo t) {
		if (ileer==null) {
			ileer = new ILeer(t); 
	    } 
			
			
	    return ileer;
	}    
	 
	 public static Instruccion nuevaIEscribir(TipoObjTipo t) {
		if (iescribir==null) {
			iescribir = new IEscribir(t); 
	    } 
	    return iescribir;
	}  
	 
	 public static Instruccion nuevaIReservar(Integer val){
    	 return new IReservar(val); 
     }
	 
	 public static Instruccion nuevaILiberar(Integer val){
    	 return new ILiberar(val); 
     }
	 
	 public static Instruccion nuevaIndefinido(String et) {
          return new IIndefinido(et); 
      } 
	 
	 public static Instruccion nuevaIMover(Integer val){
    	 return new IMover(val); 
     }
	 
     private static ISuma isuma					= null;
     private static IResta iresta				= null;
     private static IMul imul					= null;
     private static IDiv idiv					= null;
     private static IAnd iand					= null;
     private static IOr ior						= null;
     private static IEq ieq						= null;
     private static INeq ineq					= null;
     private static IGt igt						= null;
     private static IGe ige						= null;
     private static ILt ilt						= null;
     private static ILe ile						= null;
     private static IApila_true ipatrue 		= null;
     private static IApila_false ipafalse		= null;
     private static IMenos imenos 				= null;
     private static INot inot 					= null;
     private static IDesapila idesapila 		= null;
     private static ICopia icopia 				= null;
     private static IApilaInd iapilaind 		= null;
     private static IDesapilaInd idesapilaind 	= null;
     private static ILeer ileer 				= null;
     private static IEscribir iescribir 		= null;
     private static Ir_Ind iirind		 		= null;
     private static IIndefinido iindef		 	= null;
     
}
